/*
 * Copyright (c) 2001, 2002 Boris Pruessmann and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v0.5 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.perforce.core.internal.api;

import com.google.common.collect.Lists;

import net.sourceforge.perforce.api.IPerforceCommand;
import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.api.IWhereResult;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;

import java.io.File;
import java.util.List;
import java.util.Map;

/**
 * ClientUser object for the 'p4 where' command.
 * 
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 */
public class Where extends AbstractPerforceCommand implements IPerforceCommand {
  // ---------------------------------------------------------------------------
  // Private Constants

  private static final String DEPOT_APPENDER = "/Z";
  private static final String LOCAL_APPENDER = File.separator + "Z";

  // ---------------------------------------------------------------------------
  // Private Variables

  /** Stores the result of the operation. */
  private List<Result> result = Lists.newArrayList();

  // -----------------------------------------------------------------------
  // Public Static Methods

  /**
   * Convenience method for creating instances of Where.
   * 
   * @return the new Where instance.
   */
  public static final Where newInstance() {
    MultiStatus status = new MultiStatus(PerforceCorePlugin.ID, IStatus.OK, "", null);
    return new Where(status);
  }

  public static String modifyFileName(String filename) {
    return filename + DEPOT_APPENDER;
  }

  // ------------------------------------------------------------------------
  // Private Constructors

  /**
   * Constructor for Where.
   * 
   * @param status the MultiStatus object.
   */
  private Where(MultiStatus status) {
    super(status);
  }

  // -------------------------------------------------------- Public Methods
  // (IClientUserDelegate)

  @Override
  public void outputInfo(char level, String infoString) {
    if (level != '0') {
      return;
    }

    if (infoString.startsWith("-")) {
      return;
    }

    int firstStart = 0;
    int secondStart = infoString.indexOf("//", firstStart + 2); //$NON-NLS-1$
    int thirdStart = calculateThirdStart(infoString);

    Result whereResult = new Result();
    whereResult.setDepotFilename(infoString.substring(firstStart, secondStart - 1));
    whereResult.setClientFilename(infoString.substring(secondStart, thirdStart - 1));
    whereResult.setLocalFilename(infoString.substring(thirdStart));

    result.add(whereResult);
  }

  @Override
  public void outputStat(Map<String, ?> strDict) {
    Result whereResult = new Result();
    whereResult.setDepotFilename(Helper.safeGetString(strDict, "depotFile"));
    whereResult.setClientFilename(Helper.safeGetString(strDict, "clientFile"));
    whereResult.setLocalFilename(Helper.safeGetString(strDict, "path"));

    result.add(whereResult);
    System.out.println(strDict);
  }



  // ----------------------------------------------------------- Public Methods
  // (IPerforceCommand)

  public String getCommand() {
    return "where"; //$NON-NLS-1$
  }

  @Override
  public IStatus getStatus() {
    return getMultiStatus();
  }

  //----------------------------------------------------------------------------
  // -- Public Methods

  /**
   * Returns the result of the operation.
   * 
   * @return array of result objects.
   */
  public IWhereResult[] getResult() {
    return result.toArray(new IWhereResult[result.size()]);
  }

  //----------------------------------------------------------------------------
  // - Private Methods

  /**
   * Calculates the position of the third (local) path. This is a little tricky
   * as we have to deal with "null" client roots.
   * 
   * @param infoString the original infoString.
   * @return the calculated position.
   */
  private int calculateThirdStart(String infoString) {
    List<Integer> positions = Lists.newArrayList();
    int pos = infoString.lastIndexOf("//"); //$NON-NLS-1$
    while ((pos = infoString.indexOf(' ', pos + 1)) != -1) {
      positions.add(Integer.valueOf(pos));
    }

    Integer result = positions.get(positions.size() / 2);
    return result.intValue() + 1;
  }

  // ----------------------------------------------------------------------
  // Private Nested Classes

  /**
   * Implementation of the IWhereResult interface. Stores information provided
   * by the 'p4 where' command.
   * 
   * @see IWhereResult
   */
  private static class Result implements IWhereResult {
    // -----------------------------------------------------------------------
    // Private Variables

    /** Stores the filename in depot syntax. */
    private String depotFilename;
    /** Stores the filename in client syntax. */
    private String clientFilename;
    /** Stores the filename in local syntax. */
    private String localFilename;

    //--------------------------------------------------------------------------
    // Public Methods

    /** @see IWhereResult#getDepotFilename() */
    public String getDepotFilename() {
      return depotFilename;
    }

    /** @see IWhereResult#getClientFilename() */
    public String getClientFilename() {
      return clientFilename;
    }

    /** @see IWhereResult#getLocalFilename() */
    public String getLocalFilename() {
      return localFilename;
    }

    //--------------------------------------------------------------------------
    // ------- Methods

    /**
     * Sets the clientFilename.
     * 
     * @param clientFilename The clientFilename to set
     */
    void setClientFilename(String clientFilename) {
      this.clientFilename = trim(clientFilename, DEPOT_APPENDER);
    }

    /**
     * Sets the depotFilename.
     * 
     * @param depotFilename The depotFilename to set
     */
    void setDepotFilename(String depotFilename) {
      this.depotFilename = trim(depotFilename, DEPOT_APPENDER);
    }

    /**
     * Sets the localFilename.
     * 
     * @param localFilename The localFilename to set
     */
    void setLocalFilename(String localFilename) {
      this.localFilename = trim(localFilename, LOCAL_APPENDER);
    }

    // -------------------------------------------------------------------------
    // Private Methods

    private String trim(String filename, String appender) {
      if (filename.endsWith(appender)) {
        return filename.substring(0, filename.length() - appender.length());
      }

      return filename;
    }
  }
}
